<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        /* 
            原型：prototype

                我们所创建的每一个函数，解析器都会向函数对象中添加一个属性prototype，
                prototype是一个对象，所有叫原型对象

                当函数以构造函数形式调用时，它所创建的对象中都会有一个隐含的属性 __proto__，
                指向该构造函数的原型对象 

                原型对象相当于一个公共区域，所有同一个类的实例都可以访问到这个原型对象；

                创建构造函数时，可以将对象共有的属性和方法，添加到原型对象中，就可以使每个对象拥有这些属性和方法
         */

        function Person() {

        }

        console.log(Person.prototype);
        var p = new Person();
        var p1 = new Person();
        console.log(p.__proto__ == Person.prototype);

        Person.prototype.a = 123;
        Person.prototype.sayHi = function () {
            console.log("sayHi");
        }

        console.log(p.a);
        p.sayHi();
        p1.sayHi();
        /* 如果对象中没有的属性，原型中有，也会返回true */
        console.log('a' in p); //true
        /* hasOwnProperty检查自身是否含有该属性 */
        console.log(p.hasOwnProperty('a')); //false

        /* 原型是对象，也有原型对象
                hasOwnProperty属性在原型的原型对象中
         */
        console.log(p.__proto__.__proto__.hasOwnProperty('hasOwnProperty')); //true  ：第二个__proto__ 是Object 的

        /* 原型的原型并非无限的 */
        console.log(p.__proto__.__proto__.__proto__); //null


        /* 修改Person的原型的toString方法 */
        Person.prototype.toString = function () {
            console.log("我是修改后的toString方法");

        }
    </script>
</body>

</html>